/**
 * 
 */

package com.shy.portal.controller;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.shy.base.aop.LogAnnotation;
import com.shy.base.component.RedisUtil;
import com.shy.base.controller.AbsController;
import com.shy.base.shiro.EasyTypeToken;
import com.shy.base.shiro.ShiroUser;
import com.shy.base.util.GetMathExpValue;
import com.shy.base.util.StringUtils;
import com.shy.base.vo.AppConstants;
import com.shy.portal.entity.Menu;
import com.shy.portal.entity.User;
import com.shy.portal.service.MenuService;
import com.shy.portal.service.UserService;
import com.shy.portal.utils.Data2TreeVoUtils;
import com.shy.portal.vo.RoleMenuVo;

import cn.hutool.core.util.RandomUtil;

/**
 * <p>
 * Title: LoginController
 * </p>
 * <p>
 * Description:系统登錄控制器
 * </p>
 * <p>
 * Company:
 * </p>
 * 
 * @author H2013788
 */
@Controller
public class LoginController extends AbsController {
    
	/**
     * log
     */
	private Logger logger = LogManager.getLogger(this.getClass());
    
    /**
     * userService层
     */
    @Resource
    private UserService userService;

    /**
     * menuService层
     */
    @Resource
    private MenuService menuService;
    
    @Resource
    private RedisUtil redisUtil;

    /**
     * 登陸页面
     * 
     * @return 登陸页面
     * @author H2201965
     * @date 2018/2/6下午2:33:36
     */
    @RequestMapping("/")
    public String toLogin() {
        return "redirect:/login";
    }

    /**
     * GET 登录
     * 
     * @return {String}
     */
    @GetMapping("/login")
    public String login() {
        if (SecurityUtils.getSubject().isAuthenticated()) {
            return "redirect:/index";
        }
        return "sys_login";
    }
    
    
    /**
     * 首页
     * 
     * @param model
     * @return
     */
    @GetMapping("/index")
    public String index(Model model) {
        if (!SecurityUtils.getSubject().isAuthenticated()) {
            return "redirect:/login";
        }
        ShiroUser user = getShiroUser();
        String key = RandomUtil.randomString(32);
        redisUtil.set("pagekey:" + user.getLoginName(), key);
        // 加载樹形菜单
        // 查询最大菜单级別数值，用於拼裝樹形数据
        int maxLevel = menuService.getMaxLevel();
        // 当前用户可訪問的所有菜单列表
        List<Menu> menuList = userService.listMenuByUserId(user.getId());
        List<RoleMenuVo> list = new ArrayList<RoleMenuVo>();
        list = Data2TreeVoUtils.buildMenuTreeVo(maxLevel, null, menuList);
        String treeHtml = Data2TreeVoUtils.buildTreeMenu(list);
        model.addAttribute("treeHtml", treeHtml);
        model.addAttribute("key", key);
        model.addAttribute("onetab", AppConstants.configMap.get("onetab"));
        return "sys_index";
    }
    
    
    /**
     * 登陸操作
     * 
     * @param username
     *            用户名参数封裝
     * @param password
     *            密码
     * @param code
     *            code
     * @return 登陸結果
     * @author H2201965
     */
    @LogAnnotation(description = "系统登录", module = "系统登录")
    @PostMapping("login")
    public ModelAndView userLogin(@RequestParam("username") String username,
            @RequestParam("password") String password, @RequestParam("code") String code, HttpServletRequest request) {
        try {
            String exprand = request.getSession().getAttribute("exprand").toString();
            if (exprand != null) {
                if (StringUtils.isEmpty(code)) {
                    // 验证码为空
                    ModelAndView mv = new ModelAndView("sys_login");
                    mv.addObject("message", "验证码不可为空!");
                    return mv;
                } else {
                    if (!code.equals(GetMathExpValue.sizeyunsuan(exprand).replaceAll("\\.\\d+",
                            ""))) {
                        ModelAndView mv = new ModelAndView("sys_login");
                        mv.addObject("message", "验证码错误!");
                        return mv;
                    }
                }
            }
            EasyTypeToken token = new EasyTypeToken(username, password);
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            User user = userService.getUserByName(username);
            subject.getSession().setAttribute("loginUser", user);
            ModelAndView mv = new ModelAndView("redirect:/index");
            return mv; 
        } catch (IncorrectCredentialsException ice) {
            // 捕获密码错误异常
            ModelAndView mv = new ModelAndView("sys_login");
            mv.addObject("message", "密码錯誤!");
            logger.error("[ login error 密码錯誤: username-->" + username + "error:" + ice + "]");
            return mv;
        } catch (UnknownAccountException uae) {
            // 捕获未知用户名异常
            ModelAndView mv = new ModelAndView("sys_login");
            mv.addObject("message", "用户不存在!");
            logger.error("[ login error 用户不存在: username-->" + username + "error:" + uae + "]");
            return mv;
        } catch (ExcessiveAttemptsException eae) {
            // 捕获错误登录过多的异常
            ModelAndView mv = new ModelAndView("sys_login");
            mv.addObject("message", "密码錯誤超过5次，鎖定30分鐘");
            eae.printStackTrace();
            logger.error("[ login error 系统异常 : username-->" + username + "error:" + eae + "]");
            return mv;
        } catch (Exception eother) {
            ModelAndView mv = new ModelAndView("sys_login");
            mv.addObject("message", "登录超时:" + eother.getMessage());
            eother.printStackTrace();
            logger.error("[ login error 登录超时: username-->" + username + "error:" + eother + "]");
            return mv;
        }
    }

    /**
     * 登陸异常
     * @return 异常
     * @author H2201965
     */
    @RequestMapping("unauth")
    public String unauthorized() {
        return "sys_unauth";
    }
    
    /**
     * 退出
     * 
     * @return {Result}
     */
    @GetMapping("/logout")
    public Object logout() {
        Subject subject = SecurityUtils.getSubject();
        //清除redis
        //確認配置了redis后方可放開此功能
        /*if(null != getShiroUser()){
            String username = getShiroUser().getLoginName();
            OnlineUtils.logout(username);
        }*/
        //shiro退出
        subject.logout();
        //清除session
        //System.out.println(subject.getSession().getId());
        subject.getSession().setAttribute("loginUser", null);
        return "redirect:/login";
    }
    
    /**
     * session超时
     * @return
     * @author H2013788
     * @date 2018/5/14
     */
    @GetMapping("/timeout")
    public String timeout(){
        return "sys_timeout";
    }
}
